<?php
/**
 * +-------------------------------------------------------------
 * |Caption:
 * +-------------------------------------------------------------
 * |Author: Lenny
 * +-------------------------------------------------------------
 * |Email:  1685964109@qq.com
 * +-------------------------------------------------------------
 * |Date:   2024/6/21 下午5:11
 * +-------------------------------------------------------------
 */

namespace app\common\traits;

use app\Request;
use think\captcha\facade\Captcha;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Response;
use think\response\Json;
use app\common\service\annotation\NodeAnnotation;

trait LoginTrait
{
    /**
     * @NodeAnnotation (title="用户登录")
     * @param Request $request
     * @return Json
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function login(Request $request): Json
    {
        $post = $request->post();
        $this->sceneValidate($post, 'user_login');
        $admin = $this->model->where('username|phone', $post['username'])->find();

        if ($this->uid && $this->uid === $admin->id) {
            return $this->error('账号已登录');
        }

        if (empty($admin)) {
            return $this->error('用户不存在');
        }
        if (password($post['password']) != $admin->password) {
            return $this->error('密码输入有误');
        }
        if ($admin->status == 0) {
            return $this->error('账号已被禁用');
        }
        $admin->login_num       += 1;
        $admin->last_login_ip   = $request->ip();
        $admin->last_login_time = time();
        $admin->save();
        // 检测密码强度
        $is_weak = $this->isWeakPassword($post['password']);
        $admin = $admin->toArray();
        unset($admin['password']);
        // 未勾选保持登录会话过期时间为6小时
        $admin['expire_time'] = $post['keep_login'] == 1 ? true : date('Y-m-d H:i:s', time() + 7200 * 3);
        $appName              = app('http')->getName();
        // 生成会话ID
        session($appName, $admin);
        return $this->success(['is_weak' => $is_weak],'登录成功');
    }

    /**
     * 检测密码强度
     * @param string $password
     * @return bool
     */
    protected function isWeakPassword(string $password): bool
    {
        // 密码强度规则：长度 >= 8，包含大写字母、小写字母、数字和特殊字符
        if (strlen($password) < 8) {
            return true;
        }
        $hasLower   = preg_match('/[a-z]/', $password);
        $hasUpper   = preg_match('/[A-Z]/', $password);
        $hasDigit   = preg_match('/\d/', $password);
        $hasSpecial = preg_match('/[^a-zA-Z\d]/', $password);
        // 如果密码不包含大写字母、小写字母、数字和特殊字符中的任意三个，则认为是弱密码
        return !($hasLower && $hasUpper && $hasDigit && $hasSpecial);
    }

    /**
     * @NodeAnnotation (title="退出")
     */
    public function out(): Json
    {
        session(app('http')->getName(), null);
        return $this->success('退出成功');
    }

    /**
     * 验证码
     * @return Response
     */
    public function captcha(): Response
    {
        return Captcha::instance()->create();
    }
}